// wrapper/demo.go
// #cgo LDFLAGS: -L../native/libs -ldemo_sdk -lstdc++
package wrapper

import (
	"fmt"
	"swig_go_cpp/native"
	"sync"
)

type Message struct {
	ID        int
	Content   string
	Timestamp int64
}

// Go 端用户友好的接口
type IMessageObserver interface {
	OnMessage(msg Message)
	OnError(errorCode int)
}

// 适配器：将 Go 接口适配到 SWIG Director
type nativeMessageObserverAdapter struct {
	goHandler IMessageObserver
}

// 实现 SWIG Director 接口
func (a *nativeMessageObserverAdapter) OnMessage(msg native.Message) {
	a.goHandler.OnMessage(Message{
		ID:        msg.GetId(),
		Content:   msg.GetContent(),
		Timestamp: int64(msg.GetTimestamp().Swigcptr()),
	})
}

func (a *nativeMessageObserverAdapter) OnError(errorCode int) {
	a.goHandler.OnError(errorCode)
}

type SDK struct {
	nativeSDK native.MySDK
	observers map[int64]native.IMessageObserver // 防止 GC
	mu        sync.RWMutex
}

func NewSDK() *SDK {
	return &SDK{
		nativeSDK: native.NewMySDK(),
		observers: make(map[int64]native.IMessageObserver),
	}
}

func (sdk *SDK) Listen(topic string, observer IMessageObserver) (int64, error) {
	// 创建适配器
	adapter := &nativeMessageObserverAdapter{goHandler: observer}

	// 使用 SWIG 生成的 NewDirector 函数创建 Director 对象
	nativeObserver := native.NewDirectorIMessageObserver(adapter)
	if nativeObserver == nil {
		return -1, fmt.Errorf("创建 Director 对象失败")
	}

	// 调用 C++ API
	listenID := sdk.nativeSDK.Listen(topic, nativeObserver)
	listenIDValue := int64(listenID.Swigcptr())

	if listenIDValue < 0 {
		native.DeleteDirectorIMessageObserver(nativeObserver)
		return -1, fmt.Errorf("监听失败")
	}

	// ⚠️ 关键：存储引用，防止 GC 回收 Director 对象
	sdk.mu.Lock()
	sdk.observers[listenIDValue] = nativeObserver
	sdk.mu.Unlock()

	return listenIDValue, nil
}

func (sdk *SDK) Stop(listenID int64) error {
	sdk.mu.Lock()
	observer, exists := sdk.observers[listenID]
	if exists {
		delete(sdk.observers, listenID)
	}
	sdk.mu.Unlock()

	// 调用 C++ API
	sdk.nativeSDK.Stop(native.SwigcptrInt64_t(uintptr(listenID)))

	// 清理 Director 对象
	if exists && observer != nil {
		native.DeleteDirectorIMessageObserver(observer)
	}

	return nil
}
